package game
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author Nevena
	 */
	public class Board extends Sprite
	{
		private var _size:int;
		private var _fieldSize:int;
		private var _dim:int;
		private var _colorMap:Array = [0x9A9A9A, 0xFF0000];
		private var _player:int;
		private var _valueMap:Array;
		private var _score:Array = [0, 0];
		private var _players:Array = [];
		private var br:Sprite;
		
		public function Board(size:int = 8, fieldSize:int = 60)
		{
			_size = size;
			_fieldSize = fieldSize;
			_dim = _size + _fieldSize;
			_valueMap = new Array(_size);
			for (var i:int = 0; i < _size; i++)
			{
				_valueMap[i] = new Array(_size);
			}
			setPlayers();
			generateBoard();
			setInitialRocks();
			this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
		
		private function setPlayers():void 
		{
			_players.push(new PlayerController(0));
			_players.push(new PlayerController(1));
			
			//add
			var greyPlayer:PlayerController = _players[0];
			this.addChild(greyPlayer);
			var redPlayer:PlayerController = _players[1];
			this.addChild(redPlayer);
			
			//position
			greyPlayer.x += greyPlayer.width / 2;
			greyPlayer.y += greyPlayer.height / 2;
			
			redPlayer.x = _size * _fieldSize - redPlayer.width/2;
			redPlayer.y = redPlayer.height / 2;
		}
		
		private function setInitialRocks():void
		{
			insertRock(3, 3, true) && togglePlayer();
			insertRock(3, 4, true) && togglePlayer();
			insertRock(4, 4, true) && togglePlayer();
			insertRock(4, 3, true) && togglePlayer();
		}
		
		private function onAddedToStage(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			br.buttonMode = true;
			br.mouseEnabled = true;
			br.mouseChildren = false;
			br.addEventListener(MouseEvent.CLICK, onMouseClick);
		}
		
		private function onMouseClick(e:MouseEvent):void
		{
			var row:int = e.localY / _fieldSize;
			var column:int = e.localX / _fieldSize;
			insertRock(row, column) && togglePlayer();
		
		}
		
		private function insertRock(row:int, column:int, initial:Boolean = false):Boolean
		{
			var matches:Array = getMatches(row, column);
			if (initial || matches.length)
			{
				applyRock(row, column);
				applyWon(matches);
				recalculateScore();
				return true;
			}
			return false;
		}
		
		private function recalculateScore():void 
		{
			_score = [0, 0];
			for (var i:int = 0; i < _size; i++) 
			{
				for (var j:int = 0; j < _size; j++) 
				{
					var tempPlayer:Object = _valueMap[i][j];
					if (tempPlayer != null)
					{
						_score[int(tempPlayer)] = _score[int(tempPlayer)] + 1;
					}
					
				}
			}
			trace('score', _score[0], _score[1]);
			PlayerController(_players[0]).setPoints(_score[0]);
			PlayerController(_players[1]).setPoints(_score[1]);
		}
		
		private function applyWon(matches:Array):void 
		{
			for (var i:int = 0; i < matches.length; i++) 
			{
				var line:Array = matches[i];
				for (var j:int = 0; j < line.length; j++) 
				{
					applyRock(line[j].row, line[j].column);
				}
			}
		}
		
		private function togglePlayer():void
		{
			PlayerController(_players[_player]).normal();
			_player = 1 - _player;
			PlayerController(_players[_player]).onMove();
		}
		
		private function generateBoard():void
		{
			br = new Sprite();
			br.y = 55;
			this.addChild(br);
			br.graphics.beginFill(0xFFFFFF);
			br.graphics.drawRect(0, 0, _fieldSize * _size, _fieldSize * _size);
			br.graphics.endFill();
			for (var i:int = 0; i < _size; i++)
			{
				for (var j:int = 0; j < _size; j++)
				{
					drawField(i * _fieldSize, j * _fieldSize);
				}
			}
		}
		
		private function drawField(x:int, y:int):void
		{
			br.graphics.lineStyle(1, 0x000000);
			br.graphics.drawRect(x, y, _fieldSize, _fieldSize);
		}
		
		private function applyRock(row:int, column:int):void
		{
			//insert
			_valueMap[row][column] = _player;
			//draw
			br.graphics.lineStyle();
			br.graphics.beginFill(_colorMap[_player]);
			br.graphics.drawCircle((column + 1) * _fieldSize - _fieldSize / 2, (row + 1) * _fieldSize - _fieldSize / 2, _fieldSize / 2 - 5);
			br.graphics.endFill();
		}
		
		private function getMatches(currRow:int, currCol:int):Array 
		{
			var matches:Array = [];
			if (_valueMap[currRow][currCol] != undefined) return matches;
			
			var directions:Array = [ -1, 0, 1];
			
			var dr:int, dc:int;
			var tempRow:int, tempCol:int;
			var tempPlayer:Object;
			
			for (var i:int = 0; i < 3 /* directions.length */; i++) 
			{
				for (var j:int = 0; j < 3 /* directions.length */; j++) 
				{
					dr = directions[i]; 
					dc = directions[j];
					if (!dr && !dc) continue;
					tempRow = currRow + dr;
					tempCol = currCol + dc;
					var match:Array = [];
					while (tempRow >= 0 && tempCol >= 0 && tempRow <= _size-1 && tempCol <= _size-1) 
					{
						tempPlayer = _valueMap[tempRow][tempCol];
						if (tempPlayer == 1-_player)
						{
							match.push({ "row": tempRow, "column": tempCol });
						}
						else if (tempPlayer == _player && match.length)
						{
							matches.push(match);
							break;
						}
						else if (tempPlayer == _player && !match.length) break;
						else if (tempPlayer == null) break;
						tempRow += dr;
						tempCol += dc;
					}
				}
			}
			return matches;
		}
	}

}